{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-10-31T08:05:13.503599Z",
     "start_time": "2025-10-31T08:05:13.482750Z"
    }
   },
   "source": [
    "from json_utils import extract_nothink_json\n",
    "from langchain_core.messages import HumanMessage, AIMessage\n",
    "from langchain_ollama import OllamaLLM\n",
    "from langgraph.graph import StateGraph, END\n",
    "from langgraph.graph.message import add_messages\n",
    "import json\n",
    "from typing import List, Annotated\n",
    "from langchain_core.messages import BaseMessage\n",
    "\n",
    "from juputer_constants import OLLAMA_DEFAULT_MODEL\n",
    "\n",
    "\n",
    "# 工具函数\n",
    "def add_numbers_tool(a: int, b: int) -> int:\n",
    "    return a + b\n",
    "\n",
    "# 新增：获取当前时间的工具函数\n",
    "def get_current_time_tool() -> str:\n",
    "    from datetime import datetime\n",
    "    return datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n",
    "\n",
    "\n",
    "# 工具注册表\n",
    "TOOLS = {\n",
    "    \"add_numbers\": {\n",
    "        \"function\": add_numbers_tool,\n",
    "        \"description\": \"两个数字相加\",\n",
    "        \"parameters\": {\n",
    "            \"a\": \"第一个数字\",\n",
    "            \"b\": \"第二个数字\"\n",
    "        }\n",
    "    },\n",
    "    # 新增：注册获取当前时间的工具\n",
    "    \"get_current_time\": {\n",
    "        \"function\": get_current_time_tool,\n",
    "        \"description\": \"获取当前时间\",\n",
    "        \"parameters\": {}\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "# 获取工具描述信息\n",
    "def get_tools_description():\n",
    "    if not TOOLS:\n",
    "        return \"当前没有可用的工具。\"\n",
    "\n",
    "    descriptions = [\"以下是可用的工具列表：\"]\n",
    "    for tool_name, tool_info in TOOLS.items():\n",
    "        # 工具名称和描述\n",
    "        desc = f\"- {tool_name}: {tool_info['description']}\"\n",
    "\n",
    "        # 如果有参数，添加参数信息\n",
    "        if tool_info[\"parameters\"]:\n",
    "            params_desc = \", \".join([f\"{k}({v})\" for k, v in tool_info[\"parameters\"].items()])\n",
    "            desc += f\" (参数: {params_desc})\"\n",
    "        else:\n",
    "            desc += \" (无需参数)\"\n",
    "\n",
    "        descriptions.append(desc)\n",
    "\n",
    "    return \"\\n\".join(descriptions)\n",
    "\n",
    "\n",
    "# 工具调用节点\n",
    "def tool_call_node(state):\n",
    "    last_message = state[\"messages\"][-1]\n",
    "    content = last_message.content\n",
    "    try:\n",
    "        # 尝试解析JSON\n",
    "        tool_data = json.loads(extract_nothink_json(content))\n",
    "        tool_name = tool_data.get(\"tool\")\n",
    "\n",
    "        if tool_name in TOOLS:\n",
    "            # 调用相应的工具函数\n",
    "            tool_function = TOOLS[tool_name][\"function\"]\n",
    "            # 获取工具函数需要的参数（除了\"tool\"键之外的所有键值对）\n",
    "            tool_params = {k: v for k, v in tool_data.items() if k != \"tool\"}\n",
    "            result = tool_function(**tool_params)\n",
    "            return {\"messages\": [AIMessage(content=f\"工具 {tool_name} 调用结果: {result}\")]}\n",
    "        else:\n",
    "            return {\"messages\": [AIMessage(content=f\"未找到工具: {tool_name}\")]}\n",
    "    except json.JSONDecodeError:\n",
    "        return {\"messages\": [AIMessage(content=\"无法解析工具调用，请确保返回有效的JSON格式。\")]}\n",
    "\n",
    "\n",
    "# LLM 调用节点\n",
    "def call_model(state):\n",
    "    llm = OllamaLLM(model=OLLAMA_DEFAULT_MODEL)\n",
    "    # 更通用的工具调用提示模板\n",
    "    system_prompt = f\"\"\"你是一个工具调用助手。当用户请求需要执行特定任务时，请直接返回JSON格式的工具调用命令。\n",
    "\n",
    "可用的工具包括：\n",
    "{get_tools_description()}\n",
    "\n",
    "请根据用户请求选择合适的工具，并按照以下规则返回：\n",
    "1. 如果工具需要参数，请按以下JSON格式返回：\n",
    "   {{\"tool\": \"工具名称\", \"参数名1\": \"值1\", \"参数名2\": \"值2\"}}\n",
    "2. 如果工具不需要参数，请按以下JSON格式返回：\n",
    "   {{\"tool\": \"工具名称\"}}\n",
    "\n",
    "只返回JSON，不要添加其他解释或文本。\n",
    "/nothink\"\"\"\n",
    "\n",
    "    # 将系统提示和用户消息组合\n",
    "    messages = [HumanMessage(content=system_prompt)] + state[\"messages\"]\n",
    "    response = llm.invoke(messages)\n",
    "    return {\"messages\": [response]}\n",
    "\n",
    "\n",
    "# 状态类 - 使用 TypedDict 和 Annotated\n",
    "from typing_extensions import TypedDict\n",
    "\n",
    "\n",
    "class AgentState(TypedDict):\n",
    "    messages: Annotated[List[BaseMessage], add_messages]\n",
    "\n",
    "\n",
    "# 构建状态图\n",
    "graph_builder = StateGraph(AgentState)\n",
    "\n",
    "graph_builder.add_node(\"model\", call_model)\n",
    "graph_builder.add_node(\"tools\", tool_call_node)\n",
    "\n",
    "graph_builder.set_entry_point(\"model\")\n",
    "graph_builder.add_conditional_edges(\n",
    "    \"model\",\n",
    "    lambda state: \"tools\" if '{\"tool\":' in state[\"messages\"][-1].content else END,\n",
    ")\n",
    "graph_builder.add_edge(\"tools\", END)\n",
    "\n",
    "graph = graph_builder.compile()\n",
    "graph.get_graph().print_ascii()"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-----------+  \r\n",
      "| __start__ |  \r\n",
      "+-----------+  \r\n",
      "      *        \r\n",
      "      *        \r\n",
      "      *        \r\n",
      "  +-------+    \r\n",
      "  | model |    \r\n",
      "  +-------+    \r\n",
      "      *        \r\n",
      "      *        \r\n",
      "      *        \r\n",
      " +---------+   \r\n",
      " | __end__ |   \r\n",
      " +---------+   \n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-31T08:05:14.109510Z",
     "start_time": "2025-10-31T08:05:13.509593Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "display(Image(graph.get_graph().draw_mermaid_png(max_retries=5)))"
   ],
   "id": "8b199291060ec5a7",
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-31T08:05:14.130744Z",
     "start_time": "2025-10-31T08:05:14.124502Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 运行代理\n",
    "def run_agent(query: str):\n",
    "    inputs = {\"messages\": [HumanMessage(content=query)]}\n",
    "    for event in graph.stream(inputs, stream_mode=\"values\"):\n",
    "        if \"messages\" in event:\n",
    "            print(event[\"messages\"][-1].content)"
   ],
   "id": "3bfdf32c228a8cd1",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-31T08:05:27.941742Z",
     "start_time": "2025-10-31T08:05:14.150744Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 示例调用\n",
    "run_agent(\"请计算 5 + 3 的结果。\")"
   ],
   "id": "f4fa1db4bf132d2f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请计算 5 + 3 的结果。\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "{\"tool\": \"add_numbers\", \"a\": 5, \"b\": 3}\n",
      "工具 add_numbers 调用结果: 8\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-31T08:05:33.856289Z",
     "start_time": "2025-10-31T08:05:27.959185Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 新增：测试获取当前时间功能\n",
    "run_agent(\"现在几点了？\")"
   ],
   "id": "bbc730d6b9bc57c2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "现在几点了？\n",
      "<think>\n",
      "\n",
      "</think>\n",
      "\n",
      "{\"tool\": \"get_current_time\"}\n",
      "工具 get_current_time 调用结果: 2025-10-31 16:05:33\n"
     ]
    }
   ],
   "execution_count": 10
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
